﻿using System;
using System.Reflection;
using System.Reflection.Emit;

namespace SalaryQuery
{

    public class DynamicTypeBuilder
    {
        private TypeBuilder tb;

        public DynamicTypeBuilder(string typeNm)
        {
            this.tb = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("TempAssembly"), AssemblyBuilderAccess.Run).DefineDynamicModule("TempModule").DefineType(typeNm, TypeAttributes.Public);
        }

        public void AppendPublicProperty(string propertyNm, Type type)
        {
            this.AppendPublicProperty(propertyNm, type, true, true);
        }

        public void AppendPublicProperty(string propertyNm, Type type, bool canGet, bool canSet)
        {
            FieldBuilder field = this.tb.DefineField(string.Format("{0}Field", propertyNm), type, FieldAttributes.Private);
            PropertyBuilder builder2 = this.tb.DefineProperty(propertyNm, PropertyAttributes.HasDefault, type, null);
            MethodAttributes attributes = MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public;
            if (canGet)
            {
                MethodBuilder mdBuilder = this.tb.DefineMethod(string.Format("get_{0}", propertyNm), attributes, type, Type.EmptyTypes);
                ILGenerator iLGenerator = mdBuilder.GetILGenerator();
                iLGenerator.Emit(OpCodes.Ldarg_0);
                iLGenerator.Emit(OpCodes.Ldfld, field);
                iLGenerator.Emit(OpCodes.Ret);
                builder2.SetGetMethod(mdBuilder);
            }
            if (canSet)
            {
                MethodBuilder builder4 = this.tb.DefineMethod(string.Format("set_{0}", propertyNm), attributes, null, new Type[] { type });
                builder4.DefineParameter(1, ParameterAttributes.None, "value");
                ILGenerator generator2 = builder4.GetILGenerator();
                generator2.Emit(OpCodes.Ldarg_0);
                generator2.Emit(OpCodes.Ldarg_1);
                generator2.Emit(OpCodes.Stfld, field);
                generator2.Emit(OpCodes.Ret);
                builder2.SetSetMethod(builder4);
            }
        }

        public Type CreateDynamicType()
        {
            return this.tb.CreateType();
        }
    }
}


